import Icon from '@/components/Icon'
import NavBar from '@/components/NavBar'
import { useAppSelector } from '@/store'
import { addHistory, clearHistory, clearSuggestion, getSuggestion } from '@/store/action/search'
import { useEffect, useRef, useState } from 'react'
import { useDispatch } from 'react-redux'
import styles from './index.module.scss'
import DOMPurify from 'dompurify'
import { Toast } from 'antd-mobile'
import history from '@/utils/history'

// 利用正则替换高亮关键字
const highlight = (str: string, key: string) => {
  // g 表示全部匹配
  // i 表示忽略大小写
  // 🔔知识点：根据传入的变量创建正则对象
  const reg = new RegExp(`(${key})`, 'gi')
  // 替换高亮文字
  return str.replace(reg, `<span>$1</span>`)
}
// console.log(highlight('abc', 'a'))

export default function Search() {
  const [keyword, setKeyword] = useState('')
  const dispatch = useDispatch()
  const { suggestion, histories } = useAppSelector((state) => state.search)

  // 防抖步骤1：准备一个用于存储计时器id的容器
  const timerId = useRef(-1)
  const handleChange = (value: string) => {
    // 更新表单值
    setKeyword(value)
    // 防抖步骤3：清理旧的计时器
    window.clearTimeout(timerId.current)
    // 防抖步骤2：在用户操作完毕 500 毫秒后，再发送请求
    timerId.current = window.setTimeout(() => {
      // 如果关键词为空，不需要发送请求
      if (!value) return
      // 根据关键词展示搜索提示(发送请求)
      // console.log('根据关键词展示搜索提示(发送请求)', value)
      dispatch(getSuggestion(value))
    }, 500)
  }

  // // 危险的DOM代码，如果直接调用 innerHTML 写入页面会造成安全问题。
  // const dangerDOM = `
  //   <h1 onclick="alert('运行了危险脚本代码')">写入个标题</h1>
  //   <script src="xxx.js"></script>
  // `
  // const cleanDOM = DOMPurify.sanitize(dangerDOM)
  // console.log('💥危险的DOM', dangerDOM)
  // console.log('✅净化后的DOM', cleanDOM)

  // 养成习惯，组件卸载清理计时器
  useEffect(() => {
    return () => {
      window.clearTimeout(timerId.current)
    }
  }, [])

  // 清空搜索结果
  const handleClear = () => {
    // 清理 redux 中的搜索建议
    dispatch(clearSuggestion())
    // 清空输入框内容
    setKeyword('')
  }

  // 点击搜索按钮
  const handleSearch = () => {
    // console.log('点击搜索按钮，记录搜索历史记录', keyword)
    // 空提示
    if (!keyword) return Toast.show({ content: '请输入搜索内容' })
    // 把关键词添加到历史记录
    dispatch(addHistory(keyword))
    // 跳转搜索结果页
    gotoSearchResultPage(keyword)
  }

  // 去搜索结果页
  const gotoSearchResultPage = (keyword: string) => {
    // 把关键词添加到历史记录
    dispatch(addHistory(keyword))
    // 跳转搜索结果页
    history.push(`/search/result?q=${keyword}`)
  }

  // 点击清空历史记录
  const handleClearHistory = () => {
    dispatch(clearHistory())
  }

  return (
    <div className={styles.root}>
      {/* 顶部导航栏 */}
      <NavBar
        right={
          <span className='search-text' onClick={handleSearch}>
            搜索
          </span>
        }
      >
        <div className='navbar-search'>
          <Icon type='iconbtn_search' className='icon-search' />

          <div className='input-wrapper'>
            {/* 输入框 */}
            <input
              type='text'
              value={keyword}
              onChange={(e) => handleChange(e.target.value.trim())}
              placeholder='请输入关键字搜索'
              onKeyUp={(e) => {
                if (e.key === 'Enter') handleSearch()
              }}
            />

            {/* 清空输入框按钮 */}
            <Icon
              hidden={!keyword}
              type='iconbtn_tag_close'
              onClick={() => handleClear()}
              className='icon-close'
            />
          </div>
        </div>
      </NavBar>

      {/* 搜索历史 */}
      <div className='history' hidden={!!keyword}>
        <div className='history-header'>
          <span>搜索历史</span>
          <span onClick={handleClearHistory}>
            <Icon type='iconbtn_del' />
            清除全部
          </span>
        </div>

        <div className='history-list'>
          {histories.map((item, index) => (
            <span onClick={() => gotoSearchResultPage(item)} key={index} className='history-item'>
              {item}
              <span className='divider'></span>
            </span>
          ))}
        </div>
      </div>

      {/* 搜素建议结果列表 */}
      <div hidden={!keyword} className='search-result'>
        {suggestion.map((item, index) => (
          <div onClick={() => gotoSearchResultPage(item)} key={index} className='result-item'>
            <Icon className='icon-search' type='iconbtn_search' />
            {/* innerHTML 可写入 <script> 等标签，属于危险操作 */}
            <div
              className='result-value'
              dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(highlight(item, keyword)) }}
            ></div>
          </div>
        ))}
      </div>
    </div>
  )
}
